package cn.com.callback

import cn.com.elite.EliteBean
import cn.com.elite.Util
import cn.com.kh.KHDBConfig
import cn.com.kh.KHUtil
import com.jcraft.jsch.ChannelSftp
import com.jcraft.jsch.Session
import com.jcraft.jsch.SftpATTRS
import net.sf.json.JSONObject
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.jdbc.core.JdbcTemplate

import java.text.SimpleDateFormat

/**
 *
 * @Title: autoDownloadRecord* @Description:平安期货录音定时下载到服务器
 * @table:
 * @author: TH* @date 2021-12-10 10:22:00
 *
 */
public class autoDownloadRecord implements CallBackInvoke {
    private static final Logger log = LoggerFactory.getLogger(autoDownloadRecord.class);
    private static Session msshSession = null;
    private static ChannelSftp msftp = null;
    private static Session ssshSession = null;
    private static ChannelSftp ssftp = null;

    private static String Mftp_remoteRoot = null;// 主FTP默认路径
    private static String Sftp_remoteRoot = null;// 备FTP默认路径

    private static String Mftp_key = null;// 主FTP在NGS中配置文件Key
    private static String syncDayLimit = null;// 默认同步时间范围(天)
    private static String downloadPath = null;// 默认临时下载文件路径

    private static String NGS_OuterDomain = null; // NGS文件调用下载通用域
    private static int maxLoop = 100; // 每次下载任务的最大批次
    private static long sleeptime = 10; // 上传FTP时设置的时间间隔

    private static int call_num = 0; // 通话总数
    private static int record_num = 0; // 录音总数
    private static int update_num = 0; // 更新数量
    private static int insert_num = 0; // 补全数量
    private static int fail_num = 0; // 失败数量
    private static String Oper_Id = null; // 日志主键
    private static String logInfo = null; //
    private static String logInfot = null; //

    public void doCallBack(EliteBean eliteBean, String callBack, Map map, String paramString) {

        try {
            maxLoop = 100;
            NGS_OuterDomain = KHDBConfig.getAPIURL(eliteBean, "NGS-OuterDomain") + "fs/get?file=";

            syncDayLimit = KHDBConfig.getParam(eliteBean, "RECLMD");
            syncDayLimit = KHUtil.isNull(syncDayLimit) ? "-60" : syncDayLimit;

            downloadPath = KHDBConfig.getParam(eliteBean, "APITMF");

            // 加载主备FTP连接配置
            Mftp_key = KHDBConfig.getAPIURL(eliteBean, "Mftp.key");

            String Mftp_host = KHDBConfig.getAPIURL(eliteBean, "Mftp.host");
            String Mftp_username = KHDBConfig.getAPIURL(eliteBean, "Mftp.username");
            String Mftp_password = KHDBConfig.getAPIURL(eliteBean, "Mftp.password");
            String Mftp_port = KHDBConfig.getAPIURL(eliteBean, "Mftp.port");
            Mftp_remoteRoot = KHDBConfig.getAPIURL(eliteBean, "Mftp.remoteRoot");

            String Sftp_host = KHDBConfig.getAPIURL(eliteBean, "Sftp.host");
            String Sftp_username = KHDBConfig.getAPIURL(eliteBean, "Sftp.username");
            String Sftp_password = KHDBConfig.getAPIURL(eliteBean, "Sftp.password");
            String Sftp_port = KHDBConfig.getAPIURL(eliteBean, "Sftp.port");
            Sftp_remoteRoot = KHDBConfig.getAPIURL(eliteBean, "Sftp.remoteRoot");

            msshSession = Util.getjschSession(Mftp_host, Mftp_username, Integer.parseInt(Mftp_port));
            msftp = Util.sftpConnect(Mftp_password, msshSession, 10000);

            ssshSession = Util.getjschSession(Sftp_host, Sftp_username, Integer.parseInt(Sftp_port));
            ssftp = Util.sftpConnect(Sftp_password, ssshSession, 10000);

            JdbcTemplate jt = new JdbcTemplate(eliteBean.getDataSource());
            // 1-先处理常规录音-未下载过
            Oper_Id = KHUtil.getRandomString(36).toUpperCase(Locale.ROOT);
            call_num = 0;
            record_num = 0;
            update_num = 0;
            insert_num = 0;
            fail_num = 0;
            boolean isContinue = true;
            int nowLoop = 1;
            long startTime = System.currentTimeMillis();
            while (isContinue && nowLoop <= maxLoop) {

                log.debug("1-先处理常规录音-未下载过,处理次数：" + nowLoop);
                isContinue = dealRecord(eliteBean, "0", Oper_Id, jt);
                log.debug("1-先处理常规录音-未下载过,下次标识：" + isContinue);
                nowLoop++;
            }
            long Cost_Time = System.currentTimeMillis() - startTime;
            doDBLog(jt, Oper_Id, "常规录音", "Normal", "Normal", call_num, record_num, update_num, insert_num, fail_num, Cost_Time, nowLoop - 1);

            // 2-处理之前下载失败的录音
            Oper_Id = KHUtil.getRandomString(36).toUpperCase(Locale.ROOT);
            call_num = 0;
            record_num = 0;
            update_num = 0;
            insert_num = 0;
            fail_num = 0;
            isContinue = true;
            nowLoop = 1;
            startTime = System.currentTimeMillis();
            while (isContinue && nowLoop <= maxLoop) {
                log.debug("2-处理之前下载失败的录音,处理次数：" + nowLoop);
                isContinue = dealRecord(eliteBean, "-1", Oper_Id, jt);
                log.debug("2-处理之前下载失败的录音,下次标识：" + isContinue);
                nowLoop++;
            }
            Cost_Time = System.currentTimeMillis() - startTime;
            doDBLog(jt, Oper_Id, "下载失败重试", "Retry", "Retry", call_num, record_num, update_num, insert_num, fail_num, Cost_Time, nowLoop - 1);

        } catch (Exception e) {
            log.error("自动从云客服下载备份录音DownloadRecord出现异常", e);
        } finally {
            try {
                Util.disconnectSftp(msftp, msshSession);
            } catch (Exception e) {
                log.error("关闭SFTP连接资源删除[主]", e);
            } finally {
                try {
                    Util.disconnectSftp(ssftp, ssshSession);
                } catch (Exception e) {
                    log.error("关闭SFTP连接资源删除[备]", e);
                }
            }
        }

    }

    public static boolean dealRecord(EliteBean eliteBean, String Syncflag, String Oper_Id, JdbcTemplate jt) {

        boolean isContinue = false;
        log.debug("开始处理一批录音,处理类型：" + Syncflag);

        try {
            //1.查找要下载的录音
            String getRecordSQL = "";
            if (Syncflag == '0') {
                getRecordSQL = '''Select Rec_Guid, CallNo, calledno, CallSheetID, Calltype, Begin, END, Agent, FileServer, RecordFile, HangupPart, Date_format(Begin, '%Y%m%d') As FileDate
                                      From Kh_Record_Expand
                                     Where (Recordfile Is Not Null And Recordfile != '')
                                       And Syncflag = '0'
                                       And Syncnum < 3
                                       And Sync_Time >= Date_Add(Now(), Interval ''' + syncDayLimit + ''' Day)
                                       And State = 'dealing'
                                     Order By Syncnum, Begin Limit 100''';
            } else {
                getRecordSQL = '''Select Rec_Guid, CallNo, calledno, CallSheetID, Calltype, Begin, END, Agent, FileServer, RecordFile, HangupPart, Date_format(Begin, '%Y%m%d') As FileDate
                                      From Kh_Record_Expand
                                     Where (Recordfile Is Not Null And Recordfile != '')
                                       And Syncflag = '-1' And Date_Format(Date_Add(Ifnull(Synctime, Now()), Interval Syncnum Day), '%Y-%m-%d') = Date_Format(Now(), '%Y-%m-%d')
                                       And Syncnum < 3
                                       And Sync_Time >= Date_Add(Now(), Interval ''' + syncDayLimit + ''' Day)
                                       And State = 'dealing'
                                     Order By Syncnum, Synctime Limit 100''';
            }

            List RecordList = eliteBean.chaxun_sql(getRecordSQL, "dataSource");
            int RecordListsize = RecordList.size();
            call_num = call_num + RecordListsize;
            record_num = record_num + RecordListsize;
            log.debug("当前处理类型录音获取数量：" + RecordListsize);

            if (RecordList.size() > 0 && null != RecordList) {
                isContinue = true;
                for (int i = 0; i < RecordList.size(); i++) {
                    Map RecordMap = RecordList.get(i);
                    String Rec_Guid = RecordMap.get("Rec_Guid") == null ? '' : RecordMap.get("Rec_Guid");//服务器名称
                    String FileServeer = RecordMap.get("FileServer") == null ? '' : RecordMap.get("FileServer");//服务器名称
                    String RecordFile = RecordMap.get("RecordFile") == null ? '' : RecordMap.get("RecordFile");//服务器路径
                    String CallSheetID = RecordMap.get("CallSheetID") == null ? '' : RecordMap.get("CallSheetID");//CallSheetID
                    String CallNo = RecordMap.get("CallNo") == null ? '' : RecordMap.get("CallNo");//主叫号码
                    String CalledNo = RecordMap.get("CalledNo") == null ? '' : RecordMap.get("CalledNo");//被叫号码
                    String QueueTime = RecordMap.get("Begin") == null ? '' : RecordMap.get("Begin");//工作开始时间
                    String END = RecordMap.get("END") == null ? '' : RecordMap.get("END");//工作结束时间
                    String Agent = RecordMap.get("Agent") == null ? '' : RecordMap.get("Agent");//工号
                    String Calltype = RecordMap.get("Calltype") == null ? '' : RecordMap.get("Calltype");//通话类型：dialout外呼通话,normal普通来电,transfer呼入转接,dialTransfer外呼转接
                    String HangupPart = RecordMap.get("HangupPart") == null ? '' : RecordMap.get("HangupPart");//挂机类型 agent 坐席挂机， customer 客户挂机，system 系统挂机
                    String FileDate = RecordMap.get("FileDate") == null ? '' : RecordMap.get("FileDate");//挂机类型 agent 坐席挂机， customer 客户挂机，system 系统挂机
                    //2.下载录音到本地服务器
                    RecordFile = RecordFile.trim();
                    String path = FileServeer + '/' + RecordFile;
                    log.info("录音-" + i + "【" + CallSheetID + "】文件下载URL:" + path);
                    try {
                        //存入磁盘
                        String RecordFileName = KHUtil.getRandomString(6) + "_" + RecordFile.substring(RecordFile.lastIndexOf("/") + 1);
                        String saveFile = downloadPath + RecordFileName;

                        boolean downFlag = false;
                        try {
                            downFlag = Util.httpDownLoadFile(path, saveFile, 12000);
                            log.info("录音-" + i + "文件下载成功！开始上传文件服务器...");

                        } catch (Exception e) {
                            log.error("录音-" + i + "文件下载到服务器-处理异常");
                            logInfot = "文件下载到服务器-处理异常";
                        }

                        boolean uploadFlagm = false;
                        String result = "";
                        if (downFlag) {
                            try {
                                // 主文件服务器
                                uploadFlagm = uploadFile(msftp, Mftp_remoteRoot + "/" + FileDate + "/", RecordFileName, saveFile);
                                Thread.sleep(sleeptime);

                                // 备文件服务器
                                boolean uploadFlags = false;
                                try {
                                    uploadFlags = uploadFile(ssftp, Sftp_remoteRoot + "/" + FileDate + "/", RecordFileName, saveFile);
                                    Thread.sleep(sleeptime);
                                } catch (Exception e) {
                                    log.error("录音-" + i + "同步推送到备文件服务器-处理异常" + e.getMessage());
                                }

                                boolean delFlag = Util.deleteFile(saveFile); // 上传完成后将临时文件删除

                                result = NGS_OuterDomain + Mftp_key + "@" + FileDate + "/" + RecordFileName;
                                log.info("录音-" + i + "上传NGS完成...结果Master：" + uploadFlagm + " 结果Salve：" + uploadFlags + " 删除结果：" + delFlag + " NGS文件路径：" + result);
                            } catch (Exception e) {
                                log.error("录音-" + i + "上传NGS-处理异常" + e.getMessage());
                                logInfot = logInfot + System.getProperty("line.separator") + "上传NGS-处理异常" + e.getMessage();
                            }
                        }

                        if (!downFlag && !uploadFlagm) {
                            eliteBean.update("update kh_record_expand Set syncflag='-1',syncnum = syncnum+1,synctime=now(),localsyncpath='" + result + "' Where CallSheetID='" + CallSheetID + "'", "dataSource");
                            fail_num++;
                            logInfo = "录音-" + i + "录音【" + CallSheetID + "】文件下载&上传处理失败..." + logInfot;
                            doDBLog_List(jt, Oper_Id, Rec_Guid, logInfo, -2);
                            log.debug(logInfo);

                        } else {

                            //3.查询record表是否存在该录音 存在则不新增,不存在新增
                            List GhbRecordList = eliteBean.chaxun_sql("select * from record where initcallid='" + CallSheetID + "'", "dataSource");
                            if (GhbRecordList.size() <= 0) {
                                //外呼类型翻译
                                int Calltype2 = 0;
                                if (Calltype == "normal") {
                                    Calltype2 = 1;
                                } else if (Calltype == "dialout") {
                                    Calltype2 = 2;
                                }
                                int hanguptype2 = 0;
                                //挂机类型翻译
                                if (HangupPart == "agent") {
                                    hanguptype2 = 2;
                                } else if (HangupPart == "customer") {
                                    hanguptype2 = 1;
                                }
                                //先查对应的工号
                                List StaffList = eliteBean.chaxun_sql("select staff_id,DEFAULTROLEGROUP,agent_id from staff where left(agent_id,4)='" + Agent + "' limit 1", "dataSource");

                                String Staff_id = "SELITE";
                                String DEFAULTROLEGROUP = "SYSTEM";
                                String agent_id = "999999";

                                if (StaffList.size() > 0) {
                                    Map StaffListMap = StaffList.get(0);
                                    Staff_id = StaffListMap.get("staff_id") == null ? '' : StaffListMap.get("staff_id");
                                    DEFAULTROLEGROUP = StaffListMap.get("DEFAULTROLEGROUP") == null ? '' : StaffListMap.get("DEFAULTROLEGROUP");
                                    agent_id = StaffListMap.get("agent_id") == null ? '' : StaffListMap.get("agent_id");

                                }

                                //新增到Record表
                                eliteBean.update("insert into Record(record_guid,DNIS,ANI,STARTTIME,ENDTIME, STAFF_ID,Agent_ID,calltype,documentpath,initcallid,ROLEGROUP_ID,hanguptype)values(uuid(),'" + CalledNo + "','" + CallNo + "','" + QueueTime + "','" + END + "','" + Staff_id + "','" + agent_id + "','" + Calltype2 + "','" + result + "','" + CallSheetID + "','" + DEFAULTROLEGROUP + "','" + hanguptype2 + "')", "dataSource");
                                eliteBean.update("update kh_record_expand Set syncflag='1',syncnum = syncnum+1,synctime=now(),localsyncpath='" + result + "' where CallSheetID='" + CallSheetID + "' ", "dataSource");
                                insert_num++;
                                logInfo = "录音-" + i + "本条录音【" + CallSheetID + "】新增到Record表完成";
                                doDBLog_List(jt, Oper_Id, Rec_Guid, logInfo, 1);
                                log.debug(logInfo);

                            } else {
                                //更新地址
                                eliteBean.update("update Record Set Documentpath='" + result + "' Where initcallid='" + CallSheetID + "'", "dataSource");
                                eliteBean.update("update kh_record_expand Set syncflag='1',syncnum = syncnum+1,synctime=now(),localsyncpath='" + result + "' where CallSheetID='" + CallSheetID + "' ", "dataSource");
                                update_num++;
                                logInfo = "录音-" + i + "录音【" + CallSheetID + "】更新到Record表完成";
                                doDBLog_List(jt, Oper_Id, Rec_Guid, logInfo, 0);
                                log.debug(logInfo);

                            }

                        }

                    } catch (Exception e) {

                        int UpdateNum2 = eliteBean.update("update kh_record_expand Set syncflag='-1',syncnum = syncnum+1,synctime=now() Where CallSheetID='" + CallSheetID + "'", "dataSource");
                        fail_num++;
                        logInfo = "录音-" + i + "录音【" + CallSheetID + "】下载异常:" + e.getMessage() + " 录音数据标识:" + UpdateNum2.toString();
                        doDBLog_List(jt, Oper_Id, Rec_Guid, logInfo, -1);
                        log.debug(logInfo);
                    }
                }
            } else {
                log.debug("当前处理类型获取待下载录音任务空...");
                isContinue = false;
            }

        } catch (Exception e) {
            log.error("平安期货录音定时下载到服务器-处理异常" + e.getMessage());
        }
        return isContinue;
    }

    public static boolean uploadFile(ChannelSftp sftp, String remotePath, String remoteFileName, String localPath) {
        FileInputStream inf = null;
        boolean uploadFileresult = false;

        try {
            if (remotePath != null && !remotePath.equals("") && remotePath.length() > 0) {
                if (!isDirExistSftp(remotePath, sftp)) {
                    sftp.mkdir(remotePath);
                }

                sftp.cd(remotePath);
            }

            File file = new File(localPath);
            inf = new FileInputStream(file);
            sftp.put(inf, remoteFileName);
            uploadFileresult = true;
        } catch (Exception e) {
            log.error("录音上传SFTP异常", e);
        } finally {

            if (inf != null) {
                try {
                    inf.close();
                } catch (Exception e) {
                    log.error("录音上传SFTP后关闭文件流资源异常", e);
                }
            }
        }

        return uploadFileresult;
    }

    public static boolean isDirExistSftp(String directory, ChannelSftp sftp) {
        try {
            SftpATTRS sftpATTRS = sftp.lstat(directory);
            return sftpATTRS.isDir();
        } catch (Exception e) {
            log.error("处理FTP目录Directory异常:" + directory, e);
            return false;
        }
    }

    public static boolean sftpRename(ChannelSftp sftp, String oldFilename, String newFilename) {
        try {
            sftp.rename(oldFilename, newFilename);
            return true;
        } catch (Exception e) {
            log.error("处理FTP修改文件名异常", e);
            return false;
        }
    }

    public static boolean doDBLog(JdbcTemplate jt, String Oper_Id, String Title, String Business_Type, String Operator_Type, int Call_Num, int Record_Num, int Update_Num, int Insert_Num, int Fail_Num, long Cost_Time, int Deal_Times) {
        try {
            String insertSQL = '''Insert Into Sys_Syncrecord_Log
  (Oper_Id, Title, Business_Type, Operator_Type, Call_Num, Record_Num, Update_Num, Insert_Num, Fail_Num, Oper_Time, Cost_Time, Deal_Times)
Values
  (?, ?, ?, ?, ?, ?, ?, ?, ?, Now(), ?, ?)''';
            int insertNum = jt.update(insertSQL, Oper_Id, Title, Business_Type, Operator_Type, Call_Num, Record_Num, Update_Num, Insert_Num, Fail_Num, Cost_Time, Deal_Times);



            if (insertNum > 0) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            log.error("DB处理异常!", e);
            return false;
        }
        return true;
    }

    public static boolean doDBLog_List(JdbcTemplate jt, String Oper_Id, String Rec_Guid, String Oper_Desc, int Oper_Flag) {
        try {
            String insertSQL = '''Insert Into Sys_Syncrecord_Log_List
  (Oper_Id, p_Oper_Id, Rec_Guid, Oper_Time, Oper_Desc, Oper_Flag)
Values
  (UUID(), ?, ?, Now(), ?, ?)''';
            int insertNum = jt.update(insertSQL, Oper_Id, Rec_Guid, Oper_Desc, Oper_Flag);

            if (insertNum > 0) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            log.error("doDBLog_List DB处理异常!", e);
            return false;
        }
        return true;
    }
}
